package me.chyxion.spring.ext.services.support;

import java.util.Date;
import java.util.List;
import java.util.Map;
import me.chyxion.dao.mybatis.BaseMapper;
import me.chyxion.dao.mybatis.pagination.PageParam;
import me.chyxion.spring.ext.IdGenerator;
import me.chyxion.spring.ext.models.BaseModel;
import me.chyxion.spring.ext.services.BaseService;
import me.chyxion.spring.ext.utils.UUID;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

/**
 * @version 0.0.2
 * @since 0.0.1
 * @author Shaun Chyxion <br />
 * chyxion@163.com <br />
 * Oct 6, 2014 2:28:50 PM
 */
public class BaseServiceSupport<T extends BaseModel, M extends BaseMapper<T>> implements BaseService<T> {
	private static final Logger log = LoggerFactory.getLogger(BaseServiceSupport.class);

	@Autowired
	protected M mapper;
	@Autowired(required = false)
	protected IdGenerator<?> idGen;

	/*
	 * (non-Javadoc)
	 * @see me.chyxion.spring.ext.services.BaseService#list(int, int, java.util.List)
	 */
    @Override
    public Map<String, Object> list(int start, int limit, List<?> sort) {
    	if (log.isDebugEnabled()) {
    		log.debug("Page List, Start [{}], Limit [{}], Sort [{}].", new Object[]{start, limit, sort});
    	}
		PageParam<T> pp = new PageParam<T>(start, limit);
		if (sort != null && sort.size() > 0) {
			for (Object s : sort) {
				@SuppressWarnings("unchecked")
				Map<String, String> mapSort = (Map<String, String>) s;
				pp.addSort((String) mapSort.get("property"),
						(String) mapSort.get("direction"));
			}
		}
		else {
			pp.addSort("dateCreated");
		}
		mapper.listPage(pp);
		return pp.toMap();
    }

	/* (non-Javadoc)
	 * @see me.chyxion.lawnation.services.BaseService#create(java.lang.Object)
	 */
    @Override
    @Transactional
    public T[] create(T ... models) {
    	Date now = new Date();
    	for (T model : models) {
    		log.info("Create New Model [{}].", model);
    		log.debug("Use Mapper [{}].", model, mapper);
			if (model.getDateCreated() == null) {
				log.info("No Date Created, Use Now [{}].", now);
				model.setDateCreated(now);
			}
			Object id = model.getId();
			if (id == null || (id instanceof String && StringUtils.isBlank((String) id))) {
				log.info("No ID, Use UUID.");
				model.setId(idGen != null ? idGen.get() : UUID.get());
			}
		}
    	mapper.insert(models);
	    return models;
    }

	/* (non-Javadoc)
	 * @see me.chyxion.lawnation.services.BaseService#update(java.lang.Object)
	 */
    @Override
    @Transactional
    public T[] update(T ... models) {
    	Date now = new Date();
    	for (T model : models) {
			log.debug("Update Model [{}], Use Mapper [{}].", model, mapper);
			if (model.getDateUpdated() == null) {
				log.info("No Date Updated, Use Now [{}].", now);
				model.setDateUpdated(now);
			}
		}
    	mapper.update(models);
	    return models;
    }

    /*
     * (non-Javadoc)
     * @see me.chyxion.spring.ext.services.BaseService#delete(java.util.List)
     */
    @Override
    @Transactional
    public int delete(List<?> id) {
    	log.debug("Delete Models [{}], Using Mapper [{}].", id, mapper);
    	return mapper.delete(id);
    }

    /*
     * (non-Javadoc)
     * @see me.chyxion.spring.ext.services.BaseService#delete(java.lang.Object[])
     */
    @Override
    @Transactional
    public int delete(Object ... id) {
    	log.debug("Delete Models [{}], Using Mapper [{}].", id, mapper);
    	return mapper.delete(id);
    }

	/* (non-Javadoc)
	 * @see me.chyxion.lawnation.services.BaseService#find(java.lang.Object)
	 */
    @Override
    public T find(Object search) {
    	log.debug("Find Model By [{}], Using Mapper [{}].", search, mapper);
	    return mapper.find(search);
    }
}
